#include <iostream>
#include <fstream>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <cstring>
#include <map>
#include <set>
#include <cctype>
using namespace std;

void showMenu();
void choose(int);
void count(char *, int);
int find(string);
void allReplace(string, string);      //全部替换
void choReplace(string, string, int); //选择性替换
void extract();
void copy();
void trim(string &);

//变量的声明
vector<string> txt;
string str;
string eve;    //总的字符串
char *Ceve;    //字符数组
string toFind; //待查找字符串
string A;      //用B替换A
string B;
int num; //选择替换的个数
ifstream f("sleepdevil.txt");
ifstream op();

void showMenu()
{
    cout << "         菜  单         " << endl;
    cout << "0、退出                 " << endl;
    cout << "1、显示文件信息          " << endl;
    cout << "2、统计                 " << endl;
    cout << "3、查找                 " << endl;
    cout << "4、替换                 " << endl;
    cout << "5、抽取                 " << endl;
    cout << "6、文本拷贝             " << endl;
    cout << "请输入您的选择          " << endl;
}

void trim(string &s)
{
    if (s.empty())
    {
        return;
    }
    s.erase(0, s.find_first_not_of(" "));
    s.erase(s.find_last_not_of(" ") + 1);
}

void count(const char *p, int len)
{
    int minNum = len; //出现最少的次数
    int maxNum = 0;   //出现最多的次数
    vector<char> maxList;
    vector<char> minList;
    string maxStr;
    string minStr;
    map<char, int> item;
    for (int i = 0; i < len; i++)
    {
        item[p[i]]++;
    }
    for (int i = 0; i < len; i++)
    {
        if (item[p[i]] < minNum)
        {
            minNum = item[p[i]];
        }
        if (item[p[i]] > maxNum)
        {
            maxNum = item[p[i]];
        }
    }
    for (int i = 0; i < len; i++)
    {
        if (item[p[i]] == maxNum)
        {
            maxList.push_back(p[i]);
        }
        if (item[p[i]] == minNum)
        {
            minList.push_back(p[i]);
        }
    }
    set<char> o(maxList.begin(), maxList.end()); //通过集合来去重
    maxList.assign(o.begin(), o.end());
    set<char> u(minList.begin(), minList.end());
    minList.assign(u.begin(), u.end());
    if (maxList.size() > 1)
    {
        cout << "出现最多的字符分别为：" << endl;
        for (int i = 0; i < maxList.size(); i++)
            cout << maxList[i] << " ";
        cout << endl;
    }
    else
    {
        cout << "出现最多的字符为：" << maxList[0] << endl;
    }
    if (minList.size() > 1)
    {
        cout << endl;
        cout << "出现最少的字符分别为：" << endl;
        for (int i = 0; i < minList.size(); i++)
            cout << minList[i] << " ";
        cout << endl;
    }
    else
    {
        cout << "出现最少的字符为：" << minList[0] << endl;
    }
}

int find(string p)
{
    int index = 0;
    int count = 0; //该文档中含有字符串p的个数
    cout << "待查找的字符串为：" << toFind << endl;
    if (eve.find(toFind) != string::npos) //判断是否含有待查找子串
    {
        while ((index = eve.find(toFind, index)) < eve.length())
        {
            count++;
            cout << "第" << count << "个该字符串在" << index << "位置" << endl;
            index++;
        }
    }
    else
    {
        cout << "该文档不存在这个字符串！" << endl;
    }
    return count;
}

int find2(string p)
{
    int index = 0;
    int count = 0; //该文档中含有字符串p的个数
    cout << "待查找的字符串为：" << p << endl;
    if (eve.find(p) != string::npos) //判断是否含有待查找子串
    {
        while ((index = eve.find(p, index)) < eve.length())
        {
            count++;
            cout << "第" << count << "个该字符串在" << index << "位置" << endl;
            index++;
        }
    }
    else
    {
        cout << "该文档不存在这个字符串！" << endl;
    }
    return count;
}

void allReplace(string a, string b)
{
    cout << "将用" << b << "替换" << a << endl;
    int pos = eve.find(a);
    while (pos != -1)
    {
        // eve.length()求字符的长度，注意eve必须是string类型
        eve.replace(pos, string(a).length(), b);
        pos = eve.find(a);
    }
    cout << "替换完成" << endl;
    cout << "替换后为：" << eve << endl;
}

void choReplace(string a, string b, int num)
{
    cout << "将用" << b << "替换前" << num << "处" << a << endl;
    int pos = eve.find(a);
    while (num > 0)
    {
        // eve.length()求字符的长度，注意eve必须是string类型
        eve.replace(pos, string(a).length(), b);
        pos = eve.find(a);
        num--;
    }
    cout << "替换完成" << endl;
    cout << "替换后为：" << eve << endl;
}

void extract()
{
    vector<int> number; //数字
    vector<char> abc;   //字母
    vector<char> fuhao; //符号
    char n;             //用户输入
    cout << "抽取所有数字请输入1，抽取所有字母请输入2，抽取所有符号请输入3" << endl;
    cin >> n;
    switch (n)
    {
    case '1':
    {
        for (int i = 0; i < eve.length(); i++)
        {
            if (eve[i] >= 48 && eve[i] <= 57)
            {
                number.push_back(eve[i]);
            }
        }
        const char *p = "shuzi.txt";
        ofstream fout(p);
        if (fout)
        { //文件打开成功
            for (int i = 0; i < number.size(); i++)
                fout << (number[i] - 48) << endl;
            fout.close();
        }
        cout << "所有数字已经抽取完成并存放在shuzi.txt中，请查收！" << endl;
        break;
    }
    case '2':
    {
        for (int i = 0; i < eve.length(); i++)
        {
            if (isalpha(eve[i]))
            {
                abc.push_back(eve[i]);
            }
        }
        const char *p = "zimu.txt";
        ofstream fout(p);
        if (fout)
        { //文件打开成功
            for (int i = 0; i < abc.size(); i++)
                fout << abc[i] << endl;
            fout.close();
        }
        cout << "所有字母已经抽取完成并存放在zimu.txt中，请查收！" << endl;
        break;
    }
    case '3':
    {
        for (int i = 0; i < eve.length(); i++)
        {
            if ((!isalpha(eve[i])) && (!isalnum(eve[i])))
            {
                abc.push_back(eve[i]);
            }
        }
        const char *p = "fuhao.txt";
        ofstream fout(p);
        if (fout)
        { //文件打开成功
            for (int i = 0; i < abc.size(); i++)
                fout << abc[i] << endl;
            fout.close();
        }
        cout << "所有符号已经抽取完成并存放在fuhao.txt中，请查收！" << endl;
        break;
    }
    defalut:
    {
        cout << "输入错误！" << endl;
        break;
    }
    }
}

void copy()
{
    const char *p = "copy.txt";
    ofstream fout(p);
    if (fout)
    {
        fout << eve;
        fout.close();
    }
    cout << "已完成拷贝并存放在copy.txt中，请查收！" << endl;
}

const char *readFile()
{
    if (f.is_open())
    {
        while (!f.eof())
        {
            getline(f, str);
            trim(str);
            txt.push_back(str);
        }
    }
    else
    {
        cout << "文件打开出错！";
    }
    for (int i = 0; i < txt.size(); i++)
    {
        eve += txt[i];
    }
    const char *p = eve.data();
    return p;
}

int main()
{
    const char *p = readFile();
    int len = strlen(p);
    while (1)
    {
        showMenu();
        int n;
        int m;              //用户选择性替换还是全部替换
        int strCount;       //文档中含有待替换字符串的个数
        int choCount;       //用户选择替换的个数
        string txtName;     //用户打开的文件名称
        string textContent; //文本内容
        cin >> n;           //用户选择
        if (n == 0)
        {
            cout << "欢迎再次使用" << endl;
            break;
        }
        else
        {
            switch (n)
            {
            case 1:
            {
                cout << "请输入你想打开的文件名称：" << endl;
                cin >> txtName;
                const char *ctxtName = txtName.c_str();
                if (strcmp(ctxtName, "sleepdevil.txt") == 0)
                {
                    cout << eve << endl;
                    cout << "" << endl;
                    cout << "" << endl;
                }
                else
                {
                    cout << "文件不存在，将为您自动创建该文件！请输入该文件的内容：(不含中文)" << endl;
                    cin >> textContent;
                    ofstream fout(txtName);
                    if (fout)
                    { //文件打开成功
                        fout << textContent << endl;
                        fout.close();
                        eve = textContent;
                        cout << "文件创建成功，内容为：" << eve << endl;
                        cout << "" << endl;
                        cout << "" << endl;
                    }
                }
                break;
            }
            case 2:
                count(p, len);
                break;
            case 3:
                cout << "请输入想要查询的字符串：";
                cin >> toFind;
                find(toFind);
                break;
            case 4:
                cout << "全部替换请输入1，选择性替换选择2" << endl;
                cin >> m;
                if (m == 1)
                {
                    cout << "请输入替换与被替换的字符串：（例如 a b，则用b替换a）" << endl;
                    cin >> A >> B;
                    allReplace(A, B);
                }
                else if (m == 2)
                {
                    cout << "请输入想要替换的字符串，我们将告诉您该文档总共有多少个这样的字符串。" << endl;
                    cin >> A;
                    strCount = find2(A);
                    cout << "该文档中共有" << strCount << "个这样的字符串，您需要替换几个？" << endl;
                    cin >> choCount;
                    cout << "您需要将它们替换为？" << endl;
                    cin >> B;
                    choReplace(A, B, choCount);
                }
                else
                {
                    cout << "请输入正确的选项！" << endl;
                }
                break;
            case 5:
                extract();
                break;
            case 6:
                copy();
                break;
            }
        }
    }
    return 0;
}